unit Teclas;

interface

uses Classes;

type
  TTecla = record
    Key : Word;
    Shift : TShiftState;
  end;

function Tecla(const Key: Word; const Shift: TShiftState): TTecla;
function TeclaNula: TTecla;
function TeclasIguales(t1, t2: TTecla): Boolean;
function TeclaToStr(const T:TTecla):string;
function StrToTecla(const s:string):TTecla;
function TeclaToPtr(const T:TTecla):Pointer;
function PtrToTecla(const p:Pointer):TTecla;
function DescripcionTecla(T:TTecla):string;
function TeclaToShortcut(const T:TTecla):TShortCut;
function ShortcutToTecla(const s:TShortCut):TTecla;

implementation

uses Windows, SysUtils, Menus;

function Tecla(const Key: Word; const Shift: TShiftState): TTecla;
begin
  result.Key := Key;
  result.Shift := Shift;
end;

function TeclaNula: TTecla;
begin
  result.Key := 0;
  result.Shift := [];
end;

function TeclasIguales(t1, t2: TTecla): Boolean;
begin
  result := (t1.Key=t2.Key) and (t1.Shift=t2.Shift);
end;

function TeclaToStr(const T:TTecla):string;
begin
  result := '';
  if ssShift  in T.Shift then result := result + 'S';
  if ssAlt    in T.Shift then result := result + 'A';
  if ssCtrl   in T.Shift then result := result + 'C';
  if ssLeft   in T.Shift then result := result + 'L';
  if ssRight  in T.Shift then result := result + 'R';
  if ssMiddle in T.Shift then result := result + 'M';
  if ssDouble in T.Shift then result := result + 'D';
  result := result + IntToStr(T.Key);
end;

function StrToTecla(const s:string):TTecla;
  var i:Integer;
begin
 result.Shift := [];
 i:=1;
 while (i<=length(s)) and (s[i] in ['A'..'Z']) do
 begin
   case UpCase(s[i]) of
     'S' : result.Shift := result.Shift + [ssShift];
     'A' : result.Shift := result.Shift + [ssAlt];
     'C' : result.Shift := result.Shift + [ssCtrl];
     'L' : result.Shift := result.Shift + [ssLeft];
     'R' : result.Shift := result.Shift + [ssRight];
     'M' : result.Shift := result.Shift + [ssMiddle];
     'D' : result.Shift := result.Shift + [ssDouble];
   end;
   Inc(i);
 end;
 result.Key := StrToIntDef(Copy(s,i,length(s)),0);
end;

function TeclaToPtr(const T:TTecla):Pointer;
begin
  longrec(result).Lo := T.Key;
  longrec(result).Hi := byte(T.Shift);
end;

function PtrToTecla(const p:Pointer):TTecla;
begin
  result.Key := Longrec(p).Lo;
  result.Shift := TShiftState(Byte(Longrec(p).Hi));
end;

function DescripcionTecla(T:TTecla):string;
  var ds,dk:string;
begin
  ds := '';
  if ssshift in T.shift then ds := ds + 'Shift+';
  if ssalt in T.shift   then ds := ds + 'Alt+';
  if ssctrl in T.Shift  then ds := ds + 'Ctrl+';
  case T.Key of
    0  : dk := '';
    VK_RETURN : dk := 'Enter';
    VK_ESCAPE : dk := 'Esc';
    VK_DELETE : dk := 'Del';
    VK_INSERT : dk := 'Ins';
    VK_HOME   : dk := 'Home';
    VK_END    : dk := 'End';
    VK_UP     : dk := 'Up';
    VK_PRIOR  : dk := 'PgUp';
    VK_NEXT   : dk := 'PgDn';
    VK_DOWN   : dk := 'Down';
    VK_LEFT   : dk := 'Left';
    VK_RIGHT  : dk := 'Right';
    VK_NUMLOCK : dk := 'NumLock';
    VK_SCROLL  : dk := 'Scroll';
    VK_PAUSE  : dk := 'Pause';
    VK_CAPITAL : dk := 'CapsLock';
    VK_BACK : dk := 'BkSp';
    VK_TAB : dk := 'Tab';
    VK_NUMPAD0..VK_NUMPAD9 : dk := 'Num'+inttostr(T.Key-VK_NUMPAD0);
    VK_MULTIPLY : dk := 'Num*';
    VK_ADD  : dk := 'Num+';
    VK_SEPARATOR : dk := 'NumSep';
    VK_SUBTRACT : dk := 'Num-';
    VK_DECIMAL : dk := 'Num.';
    VK_DIVIDE : dk := 'Num/';
    32 : dk := 'Space';
    48..57,
    65..90    : dk := chr(T.Key);
    VK_F1..VK_F24: dk := 'F'+inttostr(T.Key-VK_F1+1);
  else
    dk := '#'+inttostr(T.Key)
  end;
  result := ds+dk;
end;

function TeclaToShortcut(const T:TTecla):TShortCut;
begin
  result := ShortCut(T.Key,T.Shift);
end;

function ShortcutToTecla(const s:TShortCut):TTecla;
begin
  ShortCutToKey(s,result.Key,result.Shift);
end;

end.
